﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace D3Calc
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
        }

        private void Main_Load(object sender, EventArgs e)
        {
            for (int i = 60; i > 0; i--)
                cmbLevel.Items.Add(i);
            cmbLevel.SelectedIndex = 0;
            cmbProfession.SelectedIndex = 0;

            string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dat");
            int index = 0;
            foreach (string file in files)
            {
                string name = file.Replace(AppDomain.CurrentDomain.BaseDirectory, "").Replace(".dat", "");                
                if (int.TryParse(name.Split('.')[0], out index))
                {
                    lstUser.Items[--index] = name;
                }
                else
                {
                    index++;
                }
            }

            ckbWiz.Items.Add("武器强化10");
            ckbWiz.Items.Add("武器强化+15");
            ckbWiz.Items.Add("弃防强攻15");
            ckbWiz.BackColor = Color.Blue;

            ckbDH.Items.Add("百步穿杨100%暴击");
            ckbDH.Items.Add("弓强化15");
            ckbDH.Items.Add("手弩强化10");
            ckbDH.Items.Add("弩强化50");
            ckbDH.Items.Add("10码无怪20");
            ckbDH.BackColor = Color.Red;

            ckbBar.Items.Add("吼15");
            ckbBar.Items.Add("吼+30");
            ckbBar.Items.Add("武器强化15");
            ckbBar.Items.Add("武器强化50");
            ckbBar.Items.Add("武器强化25");
            ckbBar.BackColor = Color.Gold;

            ckbWD.Items.Add("wd");
            ckbWD.BackColor = Color.Green;

            ckbMonk.Items.Add("monk");
            ckbMonk.BackColor = Color.Yellow;

            InitSkill(true);
        }

        #region 装备dps计算
        private void cmbProfession_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (cmbProfession.SelectedIndex)
            {
                case 0:
                    InitSkill(true);
                    break;
                case 1:
                    InitSkill(false, true);
                    break;
                case 2:
                    InitSkill(false, false, true);
                    break;
                case 3:
                    InitSkill(false, false, false, true);
                    break;
                case 4:
                    InitSkill(false, false, false, false, true);
                    break;
                default: break;
            }
        }

        private void InitSkill(bool dh = false,bool bar = false, bool wiz = false, bool wd = false, bool monk = false)
        {
            ckbDH.Enabled = dh;
            ckbBar.Enabled = bar;
            ckbWiz.Enabled = wiz;
            ckbWD.Enabled = wd;
            ckbMonk.Enabled = monk;
        }

        private void btn_Click(object sender, EventArgs e)
        {
            ShowEquipmentForm(((Button)sender));
        }

        private void ShowEquipmentForm(Button btn)
        {
            EquipmentForm equipmentForm = new EquipmentForm();
            equipmentForm.Text = btn.Text;
            Equipment equipment = null;
            if (!equipmentDic.TryGetValue(btn.Text, out equipment))
            {
                equipment = new Equipment();
                equipmentDic.Add(btn.Text, equipment);
            }
            else
            {
                equipmentForm.Init(equipment);                
            }
            equipmentForm.Change(Change, equipment);
            equipmentForm.ShowDialog();
        }

        private void Change()
        {
            Calc();
        }

        private void Calc()
        {
            Equipment equipment = new Equipment();
            double speed = 0.0;
            double dph = DPH(equipment, out speed);
            Fix(equipment);

            lblMainValue.Text = equipment.Main.ToString();
            lblCritValue.Text = equipment.Crit.ToString();
            lblHurtValue.Text = equipment.Hurt.ToString();
            lblSpeedValue.Text = Math.Round(((1 + equipment.Speed / 100) * speed), 2).ToString();
            lblDPSValue.Text = Single(dph, speed, equipment).ToString();
        }

        private double DPS(Equipment weapon)
        {
            return weapon.Avg * weapon.Speed;
        }

        private double DPH(Equipment equipment, out double speed)
        {
            double dph = 0.0;

            Equipment weapon = null;
            speed = 0.0;
            if (equipmentDic.TryGetValue(btnWeapon.Text, out weapon))
                speed = weapon.Speed;

            foreach (KeyValuePair<string,Equipment> kv in equipmentDic)
            {
                Equipment value = kv.Value;
                dph += value.Avg;
                equipment.Crit += value.Crit;
                equipment.Hurt += value.Hurt;
                equipment.Main += value.Main;
                equipment.Speed += value.Speed;
            }
            equipment.Speed -= speed;

            return dph;
        }

        private void Fix(Equipment equipment)
        {
            //main
            equipment.Main += mainArray[cmbProfession.SelectedIndex] - cmbLevel.SelectedIndex * 3;
            equipment.Crit += baseCrit;
            equipment.Hurt += baseHurt;
            //todo:skill
        }

        private double Single(double dph, double speed, Equipment equipment, params object[] passive)
        {
            double dps = dph * (speed == 0 ? 1 : speed) 
                             * (1 + equipment.Speed / 100) 
                             * (1 + equipment.Main / 100) 
                             * (1 + equipment.Crit / 100 * equipment.Hurt / 100);

           return Math.Round(dps, 2);
        }
        #endregion

        #region 存档管理
        private void btnSave_Click(object sender, EventArgs e)
        {
            if (lstUser.SelectedIndex == -1)
            {
                MessageBox.Show("请选择存档位置！");
                return;
            }

            int index = lstUser.SelectedIndex + 1;
            string name = lstUser.Items[lstUser.SelectedIndex].ToString();
            if (name != "empty" && File.Exists(AppDomain.CurrentDomain.BaseDirectory + name + ".dat"))
            {
                File.Delete(AppDomain.CurrentDomain.BaseDirectory + name + ".dat");
            }
            lstUser.Items[lstUser.SelectedIndex] = index + "."
                                                 + cmbLevel.Items[cmbLevel.SelectedIndex] + "_" 
                                                 + cmbProfession.Items[cmbProfession.SelectedIndex] 
                                                 + "_dps_" + lblDPSValue.Text;

            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair<string, Equipment> kv in equipmentDic)
            {
                sb.Append(
                    kv.Key + ":"
                    + kv.Value.Min + ","
                    + kv.Value.Max + ","
                    + kv.Value.Main + ","
                    + kv.Value.Hurt + ","
                    + kv.Value.Crit + ","
                    + kv.Value.Speed + ";");
            }

            using (FileStream fs = File.Create(AppDomain.CurrentDomain.BaseDirectory + lstUser.Items[lstUser.SelectedIndex] + ".dat"))
            {
                byte[] buffer = Encoding.UTF8.GetBytes(sb.ToString());
                fs.Write(buffer, 0, buffer.Length);                
            }
        }

        private void lstUser_DoubleClick(object sender, EventArgs e)
        {
            if (MessageBox.Show("是否载入该存档？", "载入存档", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                LoadData(lstUser.Items[lstUser.SelectedIndex].ToString());
            }
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            //LoadData(lstUser.Items[lstUser.SelectedIndex].ToString());
            BattleNet bn = new BattleNet();
            bn.ProfileLoaded = profileLoaded;
            bn.ShowDialog();
        }

        private void profileLoaded(Profile profile)
        {
            //MessageBox.Show(profile.Tag);
        }

        private void LoadData(string path)
        {
            string data = string.Empty;
            using (FileStream fs = File.Open(AppDomain.CurrentDomain.BaseDirectory + path + ".dat", FileMode.Open, FileAccess.Read))
            {
                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                data = Encoding.UTF8.GetString(buffer);
            }

            cmbLevel.SelectedIndex = 60 - int.Parse(path.Split('.')[1].Split('_')[0]);
            cmbProfession.SelectedItem = path.Split('_')[1];

            string[] equipmentArray = data.Split(';');
            equipmentDic.Clear();
            for(int i = 0; i < 13; i++)
            {
                string equipmentData = equipmentArray[i];
                string[] equipmentDicArray = equipmentData.Split(':');
                string[] equipmentDataArray = equipmentDicArray[1].Split(',');
                Equipment equipment = new Equipment();
                equipment.Min = double.Parse(equipmentDataArray[0]);
                equipment.Max = double.Parse(equipmentDataArray[1]);
                equipment.Main = double.Parse(equipmentDataArray[2]);
                equipment.Hurt = double.Parse(equipmentDataArray[3]);
                equipment.Crit = double.Parse(equipmentDataArray[4]);
                equipment.Speed = double.Parse(equipmentDataArray[5]);
                equipmentDic.Add(equipmentDicArray[0], equipment);
            }

            Change();
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (lstUser.SelectedIndex == -1)
            {
                MessageBox.Show("请选择存档位置！");
                return;
            }

            if (MessageBox.Show("是否删除该存档？", "删除存档", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                string name = lstUser.Items[lstUser.SelectedIndex].ToString();
                if (name != "empty" && File.Exists(AppDomain.CurrentDomain.BaseDirectory + name + ".dat"))
                {
                    File.Delete(AppDomain.CurrentDomain.BaseDirectory + name + ".dat");
                }
                lstUser.Items[lstUser.SelectedIndex] = "empty";
            }
        }

        #endregion

        private Dictionary<string, Equipment> equipmentDic = new Dictionary<string, Equipment>();
        private int[] mainArray = { 188, 188, 188, 187, 189 };
        private int baseCrit = 5;
        private int baseHurt = 50;
        private Dictionary<string,double> wizSkillDic = new Dictionary<string,double>();
        private Dictionary<string, double> dhSkillDic = new Dictionary<string, double>();
        private Dictionary<string, double> barSkillDic = new Dictionary<string, double>();
        private Dictionary<string, double> wdSkillDic = new Dictionary<string, double>();
        private Dictionary<string, double> monkSkillDic = new Dictionary<string, double>();
    }
}
